package com.google.code.kritter.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import twitter4j.*;

import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.code.kritter.data.FollowerStat;
import com.google.code.kritter.data.PMF;

import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.*;


public class FollowerServlet implements Servlet {
    private static final Logger log = Logger.getLogger(FollowerServlet.class.getName());
	private static ServletConfig config;
	private static String username;
	private static String password;
	private static Twitter twitter;
	private static User user;
	private static int lastFollower = 0;
	
    private static final int MAX_NEW_FOLLOWERS = 100;

	@Override
	public void destroy() {
		config = null;
		username = null;
		password = null;
		user = null;
	}

	@Override
	public ServletConfig getServletConfig() {
		return config;
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void init(ServletConfig sc) throws ServletException {
		config = sc;
		ResourceBundle bundle = ResourceBundle.getBundle("com.google.code.kritter.server.kritter");
		username = (String) bundle.getObject("kritter.username");
		password = (String) bundle.getObject("kritter.password");
		if (username != null && password != null) {
			TwitterFactory factory = new TwitterFactory();
		    twitter = factory.getInstance(username,password);
			try {
				user = twitter.verifyCredentials();
			} catch (TwitterException e) {
				user = null;
				log.severe("TwitterException verifying user credentials: " + e.getMessage());
			}
		}
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Query query = pm.newQuery(FollowerStat.class);
	    query.setOrdering("date desc");
	    query.setRange(0,1);

	    try {
	    	@SuppressWarnings("unchecked")
			List<FollowerStat> stats = (List<FollowerStat>) query.execute();
			if (stats != null && stats.size() > 0) {
				lastFollower = stats.get(0).getLastFollower();
			}
	    } finally {
	    	query.closeAll();
            pm.close();
	    }
	}

	@Override
	public void service(ServletRequest req, ServletResponse resp)
			throws ServletException, IOException {
		
        Queue queue = QueueFactory.getQueue("followers");
        
		resp.setContentType("text/plain");
		PrintWriter writer = resp.getWriter();
		try {
		    IDs followers = twitter.getFollowersIDs(user.getId());
		    final int[] ids = followers.getIDs();
		    final int stop = Math.min(MAX_NEW_FOLLOWERS, ids.length);
		    int newFollowerCount = 0;
		    int newLastFollower = 0;;
		    if (stop > 0) newLastFollower = ids[0];
		    for (int i=0; i < stop; i++) {
		    	final int id = ids[i];
		    	if (id != lastFollower) {
		    		newFollowerCount++;
			        queue.add(url("/followers/worker").param("id", String.valueOf(id)));
			        writer.println("ID: " + id);
			        User follower = twitter.showUser(String.valueOf(id));
			        writer.println("ScreenName: " + follower.getScreenName() + "\n");
			        writer.flush();
		    	} else {
		    		break;
		    	}
		    }
		    if (newFollowerCount > 0) {
				lastFollower = newLastFollower;
				FollowerStat stat = new FollowerStat(new Date(), newFollowerCount, newLastFollower);
		        log.info("newLastFollower=" + newLastFollower + ", newFollowerCount=" + newFollowerCount);
				PersistenceManager pm = PMF.get().getPersistenceManager();
		        try {
		            pm.makePersistent(stat);
		        } finally {
		            pm.close();
		        }
		    } else {
		    	writer.println("No new followers to befriend at this time.");
		    	log.info("No new followers to befriend at this time.");
		    }
		} catch (TwitterException e) {
			log.severe("TwitterException processing new followers: " + e.getMessage());
		}
		writer.close();
	}

}
